const datas = [
    [[0, 0], 0],
    [[0, 1], 0],
    [[1, 0], 0],
    [[1, 1], 1],
];

//权重
const weights = [];
for (let i = 0; i < 3; i++) {
    weights[i] = Math.random() - 0.5;
}

//激活
function calcOutput(inputs) {
    let output = inputs[0] * weights[0] + inputs[1] * weights[1] + weights[2];
    return sigmoid(output);
}

//计算误差大小
function errRate(output, excepted) {
    return Math.abs(output - excepted);
}

//计算最近n次的错误率的平均值
const errors = [];
const maxError = 20;
function calcError(err) {
    errors.push(err);
    if (errors.length > maxError) {
        errors.shift();
    }
    return errors.reduce((tep, item) => tep + item) / errors.length;
}

//试着调整每个权重
const d = 0.000001;
const trainRate = 0.01;//训练率
let times = 1;
const threshold = 0.0001;//误差率
function train(inputs, excepted) {
    let err = errRate(calcOutput(inputs), excepted);
    const dw = [];
    weights.forEach((w, i) => {
        weights[i] += d;
        let err2 = errRate(calcOutput(inputs), excepted);
        dw[i] = (err2 - err) / d;
        weights[i] = w;
    })
    weights.forEach((w, i) => {
        weights[i] -= dw[i] * trainRate;
    })
    let e = calcError(err);
    times++;
    if (times % 5000 == 0) {
        console.log(`#${times} ${e}`);
    }
    //调整每个权重 +0.00001
    return e <= threshold;
}

//激活函数
function sigmoid(x) {
    return 1 / (1 + Math.pow(Math.E, -x));
}

// console.log(sigmoid(100));
let output = calcOutput(datas[0][0]);
console.log(output, errRate(output, datas[0][1]));
for (let i = 0; ; i++) {
    let data = datas[i % datas.length];
    if (train(data[0], data[1])) {
        break;
    }
}
console.log(weights);